Early computer systems, i.e. those which operate on a single task at a time, and use a single processor in a system, did not require any locking mechanism to prevent one task or processor from being accessed simultaneously by another task or processor. In many modern computer system, multiple processors, and, in some cases, multiple tasks in each processor, attempt to access a shared resource simultaneously. The problem with such simultaneous action is that, due to a certain sequence of events, the content of the resource, or the way it is handled, may be incorrect.
Therefore, processing systems having concurrently operating processors accessing certain shared resources must have a means for synchronizing such accesses. One way of implementing such a system is the busy-waiting strategy, in which each processor makes a request for a resource and waits idly until the resource is available. When the busy resource does eventually become available, one requesting processor gains access to the resource, while others continue to await an opportunity to access.
A process called “locking” has been widely used in the industry as a means for ensuring data integrity to better control accesses of tasks and processors to shared resources. The basic idea is to lock a resource against use by other tasks or processors, while a certain task or processor is using the resource. As a result of locking, the resource becomes unavailable to all tasks or processors other than the task or processor that initiated the lock. Upon completion of the requested task or tasks by the resource, the task or processor “unlocks” the resource, effectively opening it or making it available for use by other tasks or processors of the system. Multiple approaches of handling such cases have been suggested in prior art, many of which rely on a central controlling unit, or “interest manager”, to handle the locking and permission setting for such locking mechanisms.
Many modern computer systems use a bus known as a Peripheral Component Interconnect (PCI) bus. The PCI buses have a locking mechanism, [LOCK#], to guarantee exclusive access to particular system resources whenever a device on the PCI bus requests ownership of the bus, or in other words, to perform an “atomic access”, i.e. uninterruptible access, to a resource. When LOCK# is asserted, nonexclusive transactions must proceed to an address that is not currently locked, or otherwise wait until such lock is deactivated. A grant to start a transaction on the PCI bus does not guarantee control of LOCK#. Moreover, the system requires exclusivity on a region of 16 aligned bytes. The lock mechanism that controls LOCK# must be separately implemented. By assigning a resource a lock status, the mechanism will prevent the access to such locked resource.
Many modern processors provide support for locking mechanisms such as test-and-set, compare-and-swap, or fetch-and-add. Test-and-set(t) atomically (i.e. in a single step) reads the original value of “t” and sets it to “1”. Compare-and-swap(a, b) atomically swaps the data values between “a” and “b”. Fetch-and-add (x, n) atomically reads the original value of “x” and adds “n” to it.
As the known systems for locking mechanisms are relatively time consuming and complex, there clearly exists a need in the industry for providing a system and method for efficient resource-locking mechanism, specifically for the use in PCI-based or similar systems.